package com.hulk.dryad.admin.security.token;

import cn.hutool.core.util.StrUtil;
import com.hulk.dryad.common.constant.SecurityConstants;
import org.springframework.http.HttpHeaders;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * <p>
 *
 * @author kim
 * @date 2020/10/16
 */
public class TokenAuthenticationFilter extends BasicAuthenticationFilter {

	private String tokenHeader = HttpHeaders.AUTHORIZATION;

	private TokenManager tokenManager;

	private UserDetailsService adminSysUserDetailsService;

	public TokenAuthenticationFilter(AuthenticationManager authManager, TokenManager tokenManager, UserDetailsService adminSysUserDetailsService) {
		super(authManager);
		this.tokenManager = tokenManager;
		this.adminSysUserDetailsService = adminSysUserDetailsService;
	}

	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		String authHeader = request.getHeader(this.tokenHeader);
		if(StrUtil.isBlank(authHeader)){
			//ws 建立连接 token 不能放在header中。
			authHeader = request.getParameter(this.tokenHeader);
		}
		if (authHeader != null && authHeader.startsWith(SecurityConstants.TOKEN_PREFIX.trim())) {
			final String authToken = authHeader.substring(SecurityConstants.TOKEN_PREFIX.length());
			String username = tokenManager.getUserFromToken(authToken);
			if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
				UserDetails userDetails = this.adminSysUserDetailsService.loadUserByUsername(username);
				//可以校验token和username是否有效，目前默认都是有效的
				UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
						userDetails, null, userDetails.getAuthorities());
				authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(
						request));
				logger.info("authenticated user " + username + ", setting security context");
				SecurityContextHolder.getContext().setAuthentication(authentication);
			}
		}

		chain.doFilter(request, response);
	}

}
